package ray.create;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.internal.util.StringUtility;

import java.util.ArrayList;
import java.util.List;

/**
 * generate service class
 *
 * @author ray
 * @date 2016-03-17 10:34:45
 */
public class MybatisServiceCommonPlugin extends PluginAdapter {

    private FullyQualifiedJavaType serviceType;
    private FullyQualifiedJavaType daoType;
    private FullyQualifiedJavaType interfaceType;
    //private FullyQualifiedJavaType pojoType;
    //private FullyQualifiedJavaType pojoCriteriaType;
    //private FullyQualifiedJavaType listType;
    //private FullyQualifiedJavaType returnType;
    private String servicePack;
    private String serviceImplPack;
    private String project;
    //private String pojoUrl;

    /**
     * 是否添加注解
     */
    private boolean enableAnnotation = true;
    private boolean enableFunction = false;

    public MybatisServiceCommonPlugin() {
        super();
    }

    /**
     * 读取配置文件
     */
    @Override
    public boolean validate(List<String> warnings) {

        String enableAnnotation = properties.getProperty("enableAnnotation");

        String enableFunction = properties.getProperty("enableFunction");


        if (StringUtility.stringHasValue(enableAnnotation)) {
            this.enableAnnotation = StringUtility.isTrue(enableAnnotation);
        }

        if (StringUtility.stringHasValue(enableFunction)) {
            this.enableFunction = StringUtility.isTrue(enableFunction);
        }


        this.servicePack = properties.getProperty("targetPackage");
        this.serviceImplPack = properties.getProperty("implementationPackage");
        this.project = properties.getProperty("targetProject");
        //this.pojoUrl = context.getJavaModelGeneratorConfiguration().getTargetPackage();


        return true;
    }


    /**
     *
     */
    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        List<GeneratedJavaFile> files = new ArrayList<GeneratedJavaFile>();

        String tableName = "BaseSupport";
        interfaceType = new FullyQualifiedJavaType(servicePack + "." + tableName + "Service <Entity>");

        daoType = new FullyQualifiedJavaType(introspectedTable.getMyBatis3JavaMapperType());

        serviceType = new FullyQualifiedJavaType(serviceImplPack + "." + tableName + "ServiceImpl");

        Interface interface1 = new Interface(interfaceType);
        TopLevelClass topLevelClass = new TopLevelClass(serviceType);

        // 导入必须的类
        addImport(interface1, topLevelClass);

        addLogger(topLevelClass);
        // 接口
        addService(interface1, introspectedTable, "Entity", files);


        return files;
    }

    /**
     * add interface
     *
     * @param tableName
     * @param files
     */
    protected void addService(Interface interface1, IntrospectedTable introspectedTable, String tableName, List<GeneratedJavaFile> files) {

        interface1.setVisibility(JavaVisibility.PUBLIC);
        Method method = null;
        // add method
        if (enableFunction) {

            //新增方法
            method = addEntity(introspectedTable, tableName);
            method.getBodyLines().clear();
            interface1.addMethod(method);

            //通过主键查询
            method = queryEntityById(introspectedTable, tableName);
            method.getBodyLines().clear();
            interface1.addMethod(method);

            //更新
            method = updateEntity(introspectedTable, tableName);
            method.getBodyLines().clear();
            interface1.addMethod(method);

            //删除
            method = deleteEntity(introspectedTable, tableName);
            method.getBodyLines().clear();
            interface1.addMethod(method);

            //分页查询
            method = pageQueryEntity(introspectedTable, tableName);
            method.getBodyLines().clear();
            interface1.addMethod(method);

        }
        GeneratedJavaFile file = new GeneratedJavaFile(interface1, project, context.getJavaFormatter());

        files.add(file);
    }


    /**
     * 查询对象
     *
     * @param introspectedTable
     * @param tableName
     * @return
     */
    private Method addEntity(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        FullyQualifiedJavaType javaType = new FullyQualifiedJavaType("Result<Object>");
        method.setName("add" + tableName);
        method.setReturnType(javaType);
        method.addParameter(new Parameter(new FullyQualifiedJavaType("Entity"), "entity"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType("LoginUser"), "user"));
        method.setVisibility(JavaVisibility.PUBLIC);
        return method;
    }

    /**
     * 查询对象
     *
     * @param introspectedTable
     * @param tableName
     * @return
     */
    private Method queryEntityById(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        FullyQualifiedJavaType javaType = new FullyQualifiedJavaType("Entity");
        method.setName("query" + tableName + "ById");
        method.setReturnType(javaType);
        method.addParameter(new Parameter(new FullyQualifiedJavaType("String"), "id"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType("LoginUser"), "user"));
        method.setVisibility(JavaVisibility.PUBLIC);
        return method;
    }

    /**
     * 更新对象
     *
     * @param introspectedTable
     * @param tableName
     * @return
     */
    private Method updateEntity(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        FullyQualifiedJavaType javaType = new FullyQualifiedJavaType("Result<Object>");
        method.setName("update" + tableName);
        method.setReturnType(javaType);
        method.addParameter(new Parameter(new FullyQualifiedJavaType("Entity"), "entity"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType("LoginUser"), "user"));
        method.setVisibility(JavaVisibility.PUBLIC);
        return method;
    }

    /**
     * 删除对象
     *
     * @param introspectedTable
     * @param tableName
     * @return
     */
    private Method deleteEntity(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        FullyQualifiedJavaType javaType = new FullyQualifiedJavaType("Result<Entity>");
        method.setName("delete" + tableName);
        method.setReturnType(javaType);
        method.addParameter(new Parameter(new FullyQualifiedJavaType("String"), "id"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType("LoginUser"), "user"));
        method.setVisibility(JavaVisibility.PUBLIC);
        return method;
    }

    /**
     * 删除对象
     *
     * @param introspectedTable
     * @param tableName
     * @return
     */
    private Method pageQueryEntity(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        FullyQualifiedJavaType javaType = new FullyQualifiedJavaType("PageDTO<Entity>");
        method.setName("query" + tableName);
        method.setReturnType(javaType);
        method.addParameter(new Parameter(new FullyQualifiedJavaType("Entity"), "entity"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType("PageDTO<Entity>"), "page"));
        method.addParameter(new Parameter(new FullyQualifiedJavaType("LoginUser"), "user"));
        method.setVisibility(JavaVisibility.PUBLIC);
        return method;
    }

    /**
     * 添加字段
     *
     * @param topLevelClass
     */
    protected void addField(TopLevelClass topLevelClass, String tableName) {
        // add dao
        Field field = new Field();
        field.setName(Utils.toLowerCase(daoType.getShortName())); // set var name
        topLevelClass.addImportedType(daoType);
        field.setType(daoType); // type
        field.setVisibility(JavaVisibility.PRIVATE);
        if (enableAnnotation) {
            field.addAnnotation("@Resource");
        }
        topLevelClass.addField(field);
    }


    /**
     * import must class
     */
    private void addImport(Interface interfaces, TopLevelClass topLevelClass) {
        interfaces.addImportedType(new FullyQualifiedJavaType("com.zjhc.flyhong.common.function.operator.LoginUser"));
        interfaces.addImportedType(new FullyQualifiedJavaType("com.zjhc.flyhong.common.web.Result"));
        interfaces.addImportedType(new FullyQualifiedJavaType("com.zjhc.flyhong.common.function.operator.PageDTO"));
        //interfaces.addImportedType(listType);


    }

    /**
     * import logger
     */
    private void addLogger(TopLevelClass topLevelClass) {
        Field field = new Field();
        field.setFinal(true);
        field.setInitializationString("LoggerFactory.getLogger(" + topLevelClass.getType().getShortName() + ".class)"); // set value
        field.setName("logger"); // set var name
        field.setStatic(true);
        field.setType(new FullyQualifiedJavaType("Logger")); // type
        field.setVisibility(JavaVisibility.PRIVATE);
        topLevelClass.addField(field);
    }


    public boolean clientInsertMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        //returnType = method.getReturnType();
        return true;
    }
}
